﻿#include <QApplication>
#include <QWidget>
#include <QPushButton>
#include <QVBoxLayout>
#include <QHBoxLayout>
#include <QScreen>
#include <QPixmap>
#include <QFileDialog>
#include <QLabel>
#include <QMessageBox>
#include <QShortcut>
#include <QKeySequence>
#include <QDateTime>
#include <QPainter>
#include <QMouseEvent>
#include <QDesktopWidget>
#include <QRect>
#include <QGuiApplication>
#include <QDebug>
#include <QThread>

// 截图选择区域窗口
class ScreenshotSelectWindow : public QWidget
{
    Q_OBJECT
public:
    enum DragMode
    {
        None,             // 不拖拽
        Create,           // 创建新的选择框
        Move,             // 移动整个选择框
        ResizeTopLeft,    // 拖拽左上角
        ResizeTopRight,   // 拖拽右上角
        ResizeBottomLeft, // 拖拽左下角
        ResizeBottomRight // 拖拽右下角
    };

    ScreenshotSelectWindow(QPixmap fullScreenPixmap, QWidget *parent = nullptr)
        : QWidget(parent)
        , fullPixmap(fullScreenPixmap)
        , dragMode(None)
    {
        // 设置窗口属性：无边框、置顶、全屏
        setWindowFlags(Qt::FramelessWindowHint | Qt::WindowStaysOnTopHint | Qt::Tool);
        setAttribute(Qt::WA_TranslucentBackground);
        showFullScreen();

        // 创建按钮
        confirmButton = new QPushButton("确定", this);
        cancelButton  = new QPushButton("取消", this);

        // 设置按钮样式
        QString buttonStyle
            = "QPushButton { "
              "  background-color: #1E90FF; "
              "  color: white; "
              "  border: none; "
              "  padding: 5px 15px; "
              "  border-radius: 3px; "
              "} "
              "QPushButton:hover { "
              "  background-color: #1976D2; "
              "} "
              "QPushButton:pressed { "
              "  background-color: #0D47A1; "
              "}";

        confirmButton->setStyleSheet(buttonStyle);
        cancelButton->setStyleSheet(buttonStyle);

        // 初始状态下隐藏按钮
        confirmButton->hide();
        cancelButton->hide();

        // 连接信号和槽
        connect(confirmButton, &QPushButton::clicked, this, &ScreenshotSelectWindow::confirmSelection);
        connect(cancelButton, &QPushButton::clicked, this, &ScreenshotSelectWindow::cancelSelection);

        // 设置光标为十字形
        setCursor(Qt::CrossCursor);

        // 启用鼠标跟踪，以便在不按下鼠标时也能接收mouseMoveEvent
        setMouseTracking(true);
    }

signals:
    void screenshotCaptured(const QPixmap &pixmap);
    void screenshotCancelled();

protected:
    void paintEvent(QPaintEvent *event) override
    {
        QPainter painter(this);

        // 绘制全屏截图（添加半透明暗色滤镜）
        painter.drawPixmap(0, 0, fullPixmap);

        // 添加半透明暗色遮罩
        painter.fillRect(rect(), QColor(0, 0, 0, 100));

        if (selectionRect.isValid())
        {
            // 绘制选中区域（显示原图）
            painter.drawPixmap(selectionRect, fullPixmap, selectionRect);

            // 绘制选择框
            QPen pen(QColor(0, 174, 255), 2);
            painter.setPen(pen);
            painter.drawRect(selectionRect);

            // 绘制调整大小的角点
            const int      handleSize = 8; // 稍微增大手柄尺寸，便于抓取
            QVector<QRect> handles;

            // 四个角的手柄
            handles << QRect(selectionRect.left() - handleSize / 2, selectionRect.top() - handleSize / 2, handleSize, handleSize);
            handles << QRect(selectionRect.right() - handleSize / 2, selectionRect.top() - handleSize / 2, handleSize, handleSize);
            handles << QRect(selectionRect.left() - handleSize / 2, selectionRect.bottom() - handleSize / 2, handleSize, handleSize);
            handles << QRect(selectionRect.right() - handleSize / 2, selectionRect.bottom() - handleSize / 2, handleSize, handleSize);

            // 绘制角点手柄
            painter.setBrush(QColor(0, 174, 255));
            for (const QRect &handle : handles)
            {
                painter.drawRect(handle);
            }

            // 在选择框上方绘制提示信息
            QString sizeInfo = QString("%1 x %2").arg(selectionRect.width()).arg(selectionRect.height());

            // 绘制背景矩形使文字更易读
            QFont font = painter.font();
            font.setPointSize(9);
            painter.setFont(font);

            QFontMetrics metrics(font);
            // 使用兼容性更好的width()方法而不是horizontalAdvance()
            int textWidth  = metrics.width(sizeInfo);
            int textHeight = metrics.height();
            int padding    = 4;

            QRect textRect(selectionRect.center().x() - textWidth / 2 - padding, selectionRect.top() - textHeight - padding * 2, textWidth + padding * 2, textHeight + padding * 2);

            // 如果文本框会超出屏幕顶部，则放在选择框下方
            if (textRect.top() < 0)
            {
                textRect.moveTop(selectionRect.bottom() + padding);
            }

            painter.fillRect(textRect, QColor(0, 0, 0, 180));
            painter.setPen(Qt::white);
            painter.drawText(textRect, Qt::AlignCenter, sizeInfo);

            // 更新按钮位置并显示
            updateButtonPosition();
            confirmButton->show();
            cancelButton->show();
        }
        else
        {
            confirmButton->hide();
            cancelButton->hide();
        }
    }

    void mousePressEvent(QMouseEvent *event) override
    {
        if (event->button() == Qt::LeftButton)
        {
            startPoint = event->pos();

            // 检查是否在调整柄上按下鼠标
            dragMode = getDragMode(startPoint);

            // 输出调试信息
            qDebug() << "Mouse press at:" << startPoint << "Drag mode:" << dragMode;

            // 如果不在任何调整柄上且不在选择框内，则创建新的选择框
            if (dragMode == None && !selectionRect.contains(startPoint))
            {
                selectionRect = QRect();
                dragMode      = Create;
            }

            originalRect = selectionRect; // 保存原始矩形，用于计算调整大小
            update();
        }
        QWidget::mousePressEvent(event);
    }

    // 重写mouseMoveEvent，增加鼠标悬停时更新光标的功能
    void mouseMoveEvent(QMouseEvent *event) override
    {
        QPoint currentPos = event->pos();

        // 更新光标形状，即使没有按下鼠标
        DragMode hoverMode = getDragMode(currentPos);
        updateCursorForMode(hoverMode);

        // 如果没有按下鼠标，仅更新光标后返回
        if (!(event->buttons() & Qt::LeftButton))
        {
            return;
        }

        // 计算鼠标移动距离
        QPoint delta = currentPos - startPoint;

        // 输出调试信息
        qDebug() << "Mouse move, delta:" << delta << "Drag mode:" << dragMode;

        switch (dragMode)
        {
        case Create:
            // 创建新的选择框
            endPoint      = currentPos;
            selectionRect = QRect(startPoint, endPoint).normalized();
            break;

        case Move:
            // 移动整个选择框
            selectionRect = originalRect.translated(delta);

            // 确保不超出屏幕边界
            if (selectionRect.left() < 0)
                selectionRect.moveLeft(0);
            if (selectionRect.top() < 0)
                selectionRect.moveTop(0);
            if (selectionRect.right() > width())
                selectionRect.moveRight(width());
            if (selectionRect.bottom() > height())
                selectionRect.moveBottom(height());
            break;

        case ResizeTopLeft:
            // 调整左上角
            selectionRect.setLeft(originalRect.left() + delta.x());
            selectionRect.setTop(originalRect.top() + delta.y());

            // 确保选区不会太小
            if (selectionRect.width() < 10)
                selectionRect.setLeft(selectionRect.right() - 10);
            if (selectionRect.height() < 10)
                selectionRect.setTop(selectionRect.bottom() - 10);
            break;

        case ResizeTopRight:
            // 调整右上角
            selectionRect.setRight(originalRect.right() + delta.x());
            selectionRect.setTop(originalRect.top() + delta.y());

            // 确保选区不会太小
            if (selectionRect.width() < 10)
                selectionRect.setRight(selectionRect.left() + 10);
            if (selectionRect.height() < 10)
                selectionRect.setTop(selectionRect.bottom() - 10);
            break;

        case ResizeBottomLeft:
            // 调整左下角
            selectionRect.setLeft(originalRect.left() + delta.x());
            selectionRect.setBottom(originalRect.bottom() + delta.y());

            // 确保选区不会太小
            if (selectionRect.width() < 10)
                selectionRect.setLeft(selectionRect.right() - 10);
            if (selectionRect.height() < 10)
                selectionRect.setBottom(selectionRect.top() + 10);
            break;

        case ResizeBottomRight:
            // 调整右下角
            selectionRect.setRight(originalRect.right() + delta.x());
            selectionRect.setBottom(originalRect.bottom() + delta.y());

            // 确保选区不会太小
            if (selectionRect.width() < 10)
                selectionRect.setRight(selectionRect.left() + 10);
            if (selectionRect.height() < 10)
                selectionRect.setBottom(selectionRect.top() + 10);
            break;

        case None:
            // 不做任何处理
            break;
        }

        update();
        QWidget::mouseMoveEvent(event);
    }

    void mouseReleaseEvent(QMouseEvent *event) override
    {
        if (event->button() == Qt::LeftButton)
        {
            dragMode = None;
            update();
        }
        QWidget::mouseReleaseEvent(event);
    }

    void keyPressEvent(QKeyEvent *event) override
    {
        // 按Esc键取消截图
        if (event->key() == Qt::Key_Escape)
        {
            cancelSelection();
        }
        QWidget::keyPressEvent(event);
    }

private slots:
    void confirmSelection()
    {
        if (selectionRect.isValid())
        {
            QPixmap selectedPixmap = fullPixmap.copy(selectionRect);
            emit    screenshotCaptured(selectedPixmap);
        }
        close();
    }

    void cancelSelection()
    {
        emit screenshotCancelled();
        close();
    }

private:
    void updateButtonPosition()
    {
        // 计算按钮位置（在选择框底部居中）
        const int buttonWidth   = 80;
        const int buttonHeight  = 30;
        const int buttonSpacing = 10;
        const int buttonMargin  = 10;

        confirmButton->setFixedSize(buttonWidth, buttonHeight);
        cancelButton->setFixedSize(buttonWidth, buttonHeight);

        int totalWidth = buttonWidth * 2 + buttonSpacing;
        int startX     = selectionRect.center().x() - totalWidth / 2;

        confirmButton->move(startX, selectionRect.bottom() + buttonMargin);
        cancelButton->move(startX + buttonWidth + buttonSpacing, selectionRect.bottom() + buttonMargin);
    }

    // 判断当前鼠标位置对应的拖拽模式
    DragMode getDragMode(const QPoint &pos)
    {
        if (!selectionRect.isValid())
        {
            return None;
        }

        const int handleSize = 10; // 增大调整柄的大小，使其更容易选中

        // 左上角
        if (QRect(selectionRect.left() - handleSize, selectionRect.top() - handleSize, handleSize * 2, handleSize * 2).contains(pos))
        {
            return ResizeTopLeft;
        }

        // 右上角
        if (QRect(selectionRect.right() - handleSize, selectionRect.top() - handleSize, handleSize * 2, handleSize * 2).contains(pos))
        {
            return ResizeTopRight;
        }

        // 左下角
        if (QRect(selectionRect.left() - handleSize, selectionRect.bottom() - handleSize, handleSize * 2, handleSize * 2).contains(pos))
        {
            return ResizeBottomLeft;
        }

        // 右下角
        if (QRect(selectionRect.right() - handleSize, selectionRect.bottom() - handleSize, handleSize * 2, handleSize * 2).contains(pos))
        {
            return ResizeBottomRight;
        }

        // 如果在选择框内，则为移动模式
        if (selectionRect.contains(pos))
        {
            return Move;
        }

        return None;
    }

    // 根据拖拽模式设置相应的光标
    void updateCursorForMode(DragMode mode)
    {
        switch (mode)
        {
        case ResizeTopLeft:
        case ResizeBottomRight:
            setCursor(Qt::SizeFDiagCursor);
            break;

        case ResizeTopRight:
        case ResizeBottomLeft:
            setCursor(Qt::SizeBDiagCursor);
            break;

        case Move:
            setCursor(Qt::SizeAllCursor);
            break;

        default:
            setCursor(Qt::CrossCursor);
            break;
        }
    }

    QPixmap      fullPixmap;    // 全屏截图
    QPoint       startPoint;    // 选择起始点
    QPoint       endPoint;      // 选择结束点
    QRect        selectionRect; // 选择区域
    QRect        originalRect;  // 拖拽前的原始矩形
    DragMode     dragMode;      // 当前拖拽模式
    QPushButton *confirmButton; // 确认按钮
    QPushButton *cancelButton;  // 取消按钮
};

class ScreenshotApp : public QWidget
{
    Q_OBJECT
public:
    ScreenshotApp(QWidget *parent = nullptr)
        : QWidget(parent)
    {
        // 设置窗口标题和大小
        setWindowTitle("微信风格屏幕截图工具");
        resize(800, 600);

        // 创建界面元素
        screenshotLabel = new QLabel(this);
        screenshotLabel->setAlignment(Qt::AlignCenter);
        screenshotLabel->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
        screenshotLabel->setMinimumSize(640, 480);
        screenshotLabel->setStyleSheet("border: 1px solid gray; background-color: #f0f0f0;");
        screenshotLabel->setText("截图将显示在这里");

        captureButton = new QPushButton("开始截图", this);
        saveButton    = new QPushButton("保存截图", this);
        saveButton->setEnabled(false);

        // 创建布局
        QVBoxLayout *mainLayout   = new QVBoxLayout(this);
        QHBoxLayout *buttonLayout = new QHBoxLayout();

        buttonLayout->addWidget(captureButton);
        buttonLayout->addWidget(saveButton);

        mainLayout->addWidget(screenshotLabel);
        mainLayout->addLayout(buttonLayout);

        // 连接信号和槽
        connect(captureButton, &QPushButton::clicked, this, &ScreenshotApp::startScreenCapture);
        connect(saveButton, &QPushButton::clicked, this, &ScreenshotApp::saveScreenshot);

        // 添加快捷键
        QShortcut *captureShortcut = new QShortcut(QKeySequence("Ctrl+Alt+A"), this);
        connect(captureShortcut, &QShortcut::activated, this, &ScreenshotApp::startScreenCapture);

        QShortcut *saveShortcut = new QShortcut(QKeySequence("Ctrl+S"), this);
        connect(saveShortcut, &QShortcut::activated, this, &ScreenshotApp::saveScreenshot);
    }

private slots:
    void startScreenCapture()
    {
        // 隐藏当前窗口
        this->hide();

        // 等待一点时间确保窗口已经隐藏
        QApplication::processEvents();
        QThread::msleep(200);

        // 捕获整个屏幕
        QScreen *screen = QGuiApplication::primaryScreen();
        if (!screen)
            return;

        QPixmap fullScreenPixmap = screen->grabWindow(0);

        // 创建并显示截图选择窗口
        ScreenshotSelectWindow *selectWindow = new ScreenshotSelectWindow(fullScreenPixmap);
        connect(selectWindow, &ScreenshotSelectWindow::screenshotCaptured, this, &ScreenshotApp::onScreenshotSelected);
        connect(selectWindow, &ScreenshotSelectWindow::screenshotCancelled, this, &ScreenshotApp::show);

        selectWindow->show();
    }

    void onScreenshotSelected(const QPixmap &pixmap)
    {
        if (!pixmap.isNull())
        {
            screenshot = pixmap;

            // 调整图像大小以适应标签
            QPixmap scaled = screenshot.scaled(screenshotLabel->size(), Qt::KeepAspectRatio, Qt::SmoothTransformation);

            screenshotLabel->setPixmap(scaled);
            saveButton->setEnabled(true);
        }

        // 显示主窗口
        this->show();
    }

    void saveScreenshot()
    {
        if (screenshot.isNull())
        {
            QMessageBox::warning(this, "警告", "没有可保存的截图");
            return;
        }

        // 生成默认文件名 (screenshot_yyyy-MM-dd_hh-mm-ss.png)
        QString defaultFileName = "screenshot_" + QDateTime::currentDateTime().toString("yyyy-MM-dd_hh-mm-ss") + ".png";

        QString filePath = QFileDialog::getSaveFileName(this, "保存截图", defaultFileName, "图像 (*.png *.jpg *.bmp)");

        if (!filePath.isEmpty())
        {
            if (screenshot.save(filePath))
            {
                QMessageBox::information(this, "成功", "截图已保存至: " + filePath);
            }
            else
            {
                QMessageBox::critical(this, "错误", "无法保存截图");
            }
        }
    }

private:
    QLabel      *screenshotLabel;
    QPushButton *captureButton;
    QPushButton *saveButton;
    QPixmap      screenshot;
};

// 需要添加MOC处理的Q_OBJECT声明支持
#include "main.moc"

int main(int argc, char *argv[])
{
    QApplication  app(argc, argv);
    ScreenshotApp window;
    window.show();
    return app.exec();
}
